package service

import (
	"context"
	"fmt"
	"gin_mall/conf"
	"gin_mall/dao"
	"gin_mall/model"
	"gin_mall/pkg/e"
	"gin_mall/pkg/utils"
	"gin_mall/serializer"
	"io"
	"math/rand"
	"mime/multipart"
	"os"
	"path"
	"strings"

	"gopkg.in/gomail.v2"
)

type UserService struct {
	NickName string `form:"nick_name" json:"nick_name"`
	UserName string `form:"user_name" json:"user_name"`
	Password string `form:"password" json:"password"`
	Email    string `form:"email" json:"email"`
}

// 用户注册
func (ser UserService) Register(ctx context.Context) serializer.Response {
	code := e.Success
	if len(ser.Email) < 5 || len(ser.UserName) < 2 {
		code = e.Error
		return serializer.Response{
			Status: code,
			Msg:    e.GetMsg(code),
			Error:  "用户名或者邮箱输入不正确!",
		}
	}
	userDao := dao.NewUserDao(ctx)
	_, exist := userDao.ExisUser(ser.UserName, ser.Email)
	if exist {
		code = e.ErrorExistUser
		return serializer.Response{
			Status: code,
			Msg:    e.GetMsg(code),
		}
	}
	return SendEmail(&SendEmailService{
		OperationType: 1,
		UserService:   ser,
	}, ctx)
}

// 用户登录
func (ser *UserService) Login(ctx context.Context) serializer.Response {
	code := e.Success
	userDao := dao.NewUserDao(ctx)
	user, exist := userDao.ExisUser(ser.UserName, ser.Email)
	if !exist {
		code = e.ErrorNotExistUser
		return serializer.Response{
			Status: code,
			Msg:    e.GetMsg(code),
		}
	}
	if !user.CheckPassword(ser.Password) {
		code = e.ErrorNotCompare
		return serializer.Response{
			Status: code,
			Msg:    e.GetMsg(code),
		}
	}
	token, err := utils.GenerateToken(user.ID, user.UserName)
	if err != nil {
		code = e.ErrorAuthToken
		return serializer.Response{
			Status: code,
			Msg:    e.GetMsg(code),
			Error:  err.Error(),
		}
	}
	return serializer.Response{
		Status: code,
		Data:   serializer.TokenData{User: serializer.BuildUser(user), Token: token},
		Msg:    e.GetMsg(code),
	}
}

// 更新用户昵称
func (ser *UserService) Update(ctx context.Context, id uint) serializer.Response {
	code := e.Success
	userDao := dao.NewUserDao(ctx)
	user, err := userDao.GetUserById(id)
	if err != nil {
		code = e.ErrorDataBase
		return serializer.Response{
			Status: code,
			Msg:    e.GetMsg(code),
			Error:  err.Error(),
		}
	}
	if ser.NickName != "" {
		user.NickName = ser.NickName
	}
	err = userDao.UpdateUser(user)
	if err != nil {
		code = e.ErrorDataBase
		return serializer.Response{
			Status: code,
			Msg:    e.GetMsg(code),
			Error:  err.Error(),
		}
	}
	return serializer.Response{
		Status: code,
		Data:   serializer.BuildUser(user),
		Msg:    e.GetMsg(code),
	}
}

type SendEmailService struct {
	OperationType uint `json:"type" form:"type"`
	UserService
}

func SendEmail(ses *SendEmailService, ctx context.Context) serializer.Response {
	code := e.Success
	token, err := utils.GenerateEmailToken(ses.OperationType, ses.UserName, ses.NickName, ses.Email, ses.Password)
	if err != nil {
		code = e.ErrorAuthEmailToken
		return serializer.Response{
			Status: code,
			Msg:    e.GetMsg(code),
			Error:  err.Error(),
		}
	}
	noticeDao := dao.NewNoticeDao(ctx)
	notice, err := noticeDao.GetNoticeById(ses.OperationType)
	if err != nil {
		code = e.ErrorDataBase
		return serializer.Response{
			Status: code,
			Msg:    e.GetMsg(code),
			Error:  err.Error(),
		}
	}
	body := fmt.Sprintf("<a href='%s?token=%s'>%s</a>", conf.ValidEmail, token, notice.Text)
	mail := gomail.NewMessage()
	mail.SetHeader("From", conf.SmtpEmail)
	mail.SetHeader("To", ses.Email)
	mail.SetAddressHeader("Cc", "766782821@qq.com", "Hankex") // 抄送人
	mail.SetHeader("Subject", "gin_mall")
	mail.SetBody("text/html", body)
	d := gomail.NewDialer(conf.SmtpHost, conf.SmtpPort, conf.SmtpEmail, conf.SmtpPass)
	if err := d.DialAndSend(mail); err != nil {
		code = e.ErrorSendEmailFailed
		return serializer.Response{
			Status: code,
			Msg:    e.GetMsg(code),
			Error:  err.Error(),
		}
	}
	return serializer.Response{
		Status: code,
		Msg:    e.GetMsg(code),
		Data:   "已发送验证链接到您的邮箱!",
	}
}

// 发送验证邮箱
func (ses *SendEmailService) Send(ctx context.Context) serializer.Response {
	return SendEmail(ses, ctx)
}

type ValidEmailService struct{}

// 验证邮箱激活码
func (ves *ValidEmailService) Valid(ctx context.Context, token string) serializer.Response {
	code := e.Success
	if token == "" {
		return serializer.Response{
			Status: code,
			Msg:    e.GetMsg(code),
		}
	}
	clamis, err := utils.ParseEmailToken(token)
	if err != nil {
		code = e.ErrorAuthEmailTokenFailed
		return serializer.Response{
			Status: code,
			Msg:    e.GetMsg(code),
			Error:  err.Error(),
		}
	}
	userDao := dao.NewUserDao(ctx)
	user, exist := userDao.ExisUser(clamis.UserName, clamis.Email)
	tipStr := "用户激活成功"
	isOk := true
	switch clamis.OperationType {
	case 1: // 1用户激活
		if exist {
			isOk = false
			tipStr = "该用户已经存在!"
		} else {
			user = &model.User{
				UserName: clamis.UserName,
				Email:    clamis.Email,
				NickName: clamis.NickName,
				Status:   model.Active,
				Money:    utils.Encode("10000"),
				Avater:   fmt.Sprintf("%d.jpg", rand.Intn(5)),
			}
			user.SetPassword(clamis.Password)
		}
	case 2: // 2解绑邮箱
		if exist && len(user.Email) > 5 {
			user.Email = ""
			tipStr = "解绑邮箱成功!"
		} else {
			isOk = false
			tipStr = "该邮箱不存在!"
		}
	case 3: // 3绑定邮箱
		if exist && user.Email == "" {
			user.Email = clamis.Email
			tipStr = "绑定邮箱成功!"
		} else {
			isOk = false
			tipStr = "改邮箱已经存在，不能重复绑定!"
		}
	case 4: // 4更改密码
		if exist {
			if len(user.Email) > 5 {
				user.SetPassword(clamis.Password)
				tipStr = "更改密码完成!"
			} else {
				tipStr = "邮箱未绑定!"
			}
		} else {
			tipStr = "该用户不存在!"
		}
	}

	if !isOk {
		code = e.InvalidParams
		return serializer.Response{
			Status: code,
			Msg:    e.GetMsg(code),
			Data:   tipStr,
		}
	}
	err = userDao.CreateUser(user)
	if err != nil {
		code = e.ErrorDataBase
		return serializer.Response{
			Status: code,
			Msg:    e.GetMsg(code),
			Error:  err.Error(),
		}
	}
	return serializer.Response{
		Status: code,
		Msg:    e.GetMsg(code),
		Data:   tipStr,
	}
}

// 上传图片
func (ser UserService) Post(ctx context.Context, id uint, file multipart.File, filename string) serializer.Response {
	code := e.Success
	fileExt := strings.ToLower(path.Ext(filename))
	if utils.VerifyTheFileFormatByExt(fileExt, []string{".png", ".jpg", ".jpeg", ".gif"}) {
		code = e.ErrorFileExt
		return serializer.Response{
			Status: code,
			Msg:    e.GetMsg(code),
			Data:   "文件仅支持png,jpg,gif,jpeg格式",
		}
	}
	userDao := dao.NewUserDao(ctx)
	user, err := userDao.GetUserById(id)
	if err != nil {
		code = e.ErrorDataBase
		return serializer.Response{
			Status: code,
			Msg:    e.GetMsg(code),
			Error:  err.Error(),
		}
	}
	path := user.GetAvatarDir(fileExt)
	fileDir := fmt.Sprintf(".%s%s", conf.AvatarPath, path)
	exist := utils.DirExistOrNot(fileDir)
	if !exist {
		err = os.Mkdir(fileDir, os.ModePerm)
		if err != nil {
			fmt.Println("创建文件失败:", err.Error())
		}
	}
	bytes, _ := io.ReadAll(file)
	ok := utils.SaveFile(fmt.Sprintf(".%s%s", conf.AvatarPath, user.Avater), bytes)
	if !ok {
		code = e.ErrorUploadFileFail
		return serializer.Response{
			Status: code,
			Msg:    e.GetMsg(code),
			Error:  err.Error(),
		}
	}
	err = userDao.UpdateUser(user)
	if err != nil {
		code = e.ErrorDataBase
		return serializer.Response{
			Status: code,
			Msg:    e.GetMsg(code),
			Error:  err.Error(),
		}
	}
	return serializer.Response{
		Status: code,
		Data:   serializer.BuildUser(user),
		Msg:    e.GetMsg(code),
	}
}
